unit UCellButton;

interface

uses SysUtils, Types, Classes, Grids, Controls, Graphics, ImgList,
  Generics.Collections;

const
  SchedButtonHeight = 16;
  SchedButtonWidth = 16;

type
  TButtonType = (btConflict, btUp, btDown, btModify, btAdd, btDel, btNone);

  TButtonTypes = set of TButtonType;

  PButtonTypes = ^TButtonTypes;

  TCellButton = class(TObject)
    Rect: TRect;
    ButtonType: TButtonType;
    OnClick: TNotifyEvent;
    procedure Draw(const CellRect: TRect; c: TCanvas);
    function HitTest(const P: TPoint; const CellRect: TRect): boolean;
    constructor Create(AButtonType: TButtonType); reintroduce; overload;
  end;

  TSchedCellButtonManager = class(TObjectList<TCellButton>)
    procedure UpdatePositions(const Buttons: TButtonTypes;
      const CellRect: TRect);
    procedure DrawButtons(const CellRect: TRect; c: TCanvas;
      const Buttons: TButtonTypes);
    function HitTest(const P: TPoint; const CellRect: TRect;
      const Buttons: TButtonTypes): TButtonType;
    constructor Create;
  end;

var
  ButtonImages: TImageList;

function SchedButtonManager: TSchedCellButtonManager;

implementation

var
  SchedBtMgr: TSchedCellButtonManager;

function SchedButtonManager: TSchedCellButtonManager;
begin
  Result := SchedBtMgr;
end;

{ TCellButton }

constructor TCellButton.Create(AButtonType: TButtonType);
begin
  ButtonType := AButtonType;
end;

procedure TCellButton.Draw(const CellRect: TRect; c: TCanvas);
begin
  ButtonImages.DrawingStyle := dsTransparent;
  ButtonImages.Draw(c, Rect.Left + CellRect.Left, Rect.Top + CellRect.Top,
    Ord(ButtonType));
end;

function TCellButton.HitTest(const P: TPoint; const CellRect: TRect): boolean;
var
  R: TRect;
begin
  R := Rect;
  OffsetRect(R, CellRect.Left, CellRect.Top);
  Result := PtInRect(R, P) and PtInRect(CellRect, P);
end;

{ TCellButtonManager }

constructor TSchedCellButtonManager.Create;
var
  i: TButtonType;
begin
  inherited;
  for i := low(TButtonType) to btDel do
    Add(TCellButton.Create(i));
end;

procedure TSchedCellButtonManager.DrawButtons(const CellRect: TRect;
  c: TCanvas; const Buttons: TButtonTypes);
var
  b: TCellButton;
begin
  UpdatePositions(Buttons, Cellrect);
  for b in Self do begin
    if not(b.ButtonType in Buttons) then
      Continue;
    b.Draw(CellRect, c);
  end;
end;

function TSchedCellButtonManager.HitTest(const P: TPoint;
  const CellRect: TRect; const Buttons: TButtonTypes): TButtonType;
var
  b: TCellButton;
begin
  UpdatePositions(Buttons, CellRect);
  for b in Self do begin
    if not(b.ButtonType in Buttons) then
      Continue;
    if b.HitTest(P, CellRect) then
      Exit(b.ButtonType);
  end;
  Result := btNone;
end;

procedure TSchedCellButtonManager.UpdatePositions(const Buttons: TButtonTypes;
  const CellRect: TRect);
var
  R: TRect;
  b: TCellButton;
  i: integer;
begin
  R := Rect(0, 0, SchedButtonWidth, SchedButtonHeight);
  OffsetRect(R, CellRect.Right - CellRect.Left - SchedButtonWidth - 3, 3);
  for i := Count - 1 downto 0 do begin
    b := Items[i];
    if not(b.ButtonType in Buttons) then
      Continue;
    b.Rect := R;
    dec(R.Left, SchedButtonWidth);
    dec(R.Right, SchedButtonWidth);
  end;
end;

initialization
  SchedBtMgr := TSchedCellButtonManager.Create;

finalization
  FreeAndNil(SchedBtMgr);

end.
